package cn.monkey.family.server.domain.shop.order;

import cn.monkey.family.data.Result;
import cn.monkey.family.data.Results;
import cn.monkey.family.data.context.RequestContext;
import cn.monkey.family.data.crud.AbstractCrudService;
import cn.monkey.family.data.shop.order.*;
import com.google.common.base.Strings;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;

@Service
public class OrderService extends AbstractCrudService<String, OrderQueryRequest, Order, OrderDto, OrderVo, OrderMapper, OrderRepository>
        implements IOrderService {
    protected final OrderDetailRepository orderDetailRepository;
    protected final BeforeOrderCreateEventListener beforeOrderCreateEventListener;

    public OrderService(OrderRepository repository,
                        OrderMapper mapper,
                        OrderDetailRepository orderDetailRepository,
                        BeforeOrderCreateEventListener beforeOrderCreateEventListener) {
        super(repository, mapper);
        this.orderDetailRepository = orderDetailRepository;
        this.beforeOrderCreateEventListener = beforeOrderCreateEventListener;
    }


    protected Result<OrderQueryRequest> rebuildQueryRequest(OrderQueryRequest orderQueryRequest) {
        OrderDetailQueryRequest detailQueryRequest = orderQueryRequest.toDetailQueryRequest();
        if (Strings.isNullOrEmpty(detailQueryRequest.getItemName())) {
            return Results.ok(orderQueryRequest);
        }
        List<OrderDetail> orderDetailList = this.orderDetailRepository.findAllByQueryRequest(orderQueryRequest.toDetailQueryRequest(), Sort.unsorted());
        if (CollectionUtils.isEmpty(orderDetailList)) {
            return Results.fail("EMPTY_DATA");
        }
        return Results.ok(orderQueryRequest.toBuilder().detailIds(orderDetailList.stream().map(OrderDetail::getSkuId).toArray(String[]::new)).build());
    }

    @Override
    public Result<OrderVo> readOne(RequestContext requestContext, OrderQueryRequest queryRequest) {
        Result<OrderQueryRequest> orderQueryRequestResult = this.rebuildQueryRequest(queryRequest);
        if (!Results.isOk(orderQueryRequestResult)) {
            return Results.fromFailOrError(orderQueryRequestResult);
        }
        return super.readOne(requestContext, orderQueryRequestResult.getData());
    }

    @Override
    public Result<Collection<OrderVo>> readAll(RequestContext requestContext, OrderQueryRequest queryRequest) {
        Result<OrderQueryRequest> orderQueryRequestResult = this.rebuildQueryRequest(queryRequest);
        if (!Results.isOk(orderQueryRequestResult)) {
            return Results.fromFailOrError(orderQueryRequestResult);
        }
        return super.readAll(requestContext, orderQueryRequestResult.getData());
    }

    @Override
    public Result<Collection<OrderVo>> readAll(RequestContext requestContext, OrderQueryRequest queryRequest, Sort sort) {
        Result<OrderQueryRequest> orderQueryRequestResult = this.rebuildQueryRequest(queryRequest);
        if (!Results.isOk(orderQueryRequestResult)) {
            return Results.fromFailOrError(orderQueryRequestResult);
        }
        return super.readAll(requestContext, orderQueryRequestResult.getData(), sort);
    }

    @Override
    public Result<Page<OrderVo>> readPage(RequestContext requestContext, OrderQueryRequest queryRequest, Pageable pageable) {
        Result<OrderQueryRequest> orderQueryRequestResult = this.rebuildQueryRequest(queryRequest);
        if (!Results.isOk(orderQueryRequestResult)) {
            return Results.fromFailOrError(orderQueryRequestResult);
        }
        return super.readPage(requestContext, queryRequest, pageable);
    }

    @Override
    public Result<OrderVo> create(RequestContext requestContext, OrderDto orderDto) {
        Result<Void> result = this.beforeOrderCreateEventListener.beforeOrderCreated(requestContext, orderDto);
        if (!Results.isOk(result)) {
            return Results.fromFailOrError(result);
        }
        return super.create(requestContext, orderDto);
    }
}
